<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML
><HEAD
><TITLE
>Parameter Substitution</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="Advanced Bash-Scripting Guide"
HREF="index.html"><LINK
REL="UP"
TITLE="Manipulating Variables"
HREF="manipulatingvars.html"><LINK
REL="PREVIOUS"
TITLE="Manipulating Strings"
HREF="string-manipulation.html"><LINK
REL="NEXT"
TITLE="Loops and Branches"
HREF="loops.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Advanced Bash-Scripting Guide: </TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="string-manipulation.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 10. Manipulating Variables</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="loops.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="PARAMETER-SUBSTITUTION"
></A
>10.2. Parameter Substitution</H1
><P
><A
NAME="PARAMSUBREF"
></A
></P
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
><A
NAME="PSSUB1"
></A
>Manipulating and/or expanding variables</B
></P
><DL
><DT
><TT
CLASS="USERINPUT"
><B
>${parameter}</B
></TT
></DT
><DD
><P
>Same as <TT
CLASS="REPLACEABLE"
><I
>$parameter</I
></TT
>, i.e.,
		  value of the variable
		  <TT
CLASS="REPLACEABLE"
><I
>parameter</I
></TT
>.
		  In certain contexts, only the less ambiguous
		  <TT
CLASS="REPLACEABLE"
><I
>${parameter}</I
></TT
> form
		  works.</P
><P
>May be used for concatenating variables with strings.</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>your_id=${USER}-on-${HOSTNAME}
echo "$your_id"
#
echo "Old \$PATH = $PATH"
PATH=${PATH}:/opt/bin  # Add /opt/bin to $PATH for duration of script.
echo "New \$PATH = $PATH"</PRE
></FONT
></TD
></TR
></TABLE
></P
></DD
><DT
><A
NAME="DEFPARAM1"
></A
><TT
CLASS="USERINPUT"
><B
>${parameter-default}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${parameter:-default}</B
></TT
></DT
><DD
><P
>If parameter not set, use default.</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>var1=1
var2=2
# var3 is unset.

echo ${var1-$var2}   # 1
echo ${var3-$var2}   # 2
#           ^          Note the $ prefix.



echo ${username-`whoami`}
# Echoes the result of `whoami`, if variable $username is still unset.</PRE
></FONT
></TD
></TR
></TABLE
></P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
><A
NAME="UNDDR"
></A
><TT
CLASS="REPLACEABLE"
><I
>${parameter-default}</I
></TT
>
		  and <TT
CLASS="REPLACEABLE"
><I
>${parameter:-default}</I
></TT
>
		  are almost equivalent. The extra <SPAN
CLASS="TOKEN"
>:</SPAN
> makes
		  a difference only when <TT
CLASS="PARAMETER"
><I
>parameter</I
></TT
>
		  has been declared, but is null.  </P
></TD
></TR
></TABLE
></DIV
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# param-sub.sh

#  Whether a variable has been declared
#+ affects triggering of the default option
#+ even if the variable is null.

username0=
echo "username0 has been declared, but is set to null."
echo "username0 = ${username0-`whoami`}"
# Will not echo.

echo

echo username1 has not been declared.
echo "username1 = ${username1-`whoami`}"
# Will echo.

username2=
echo "username2 has been declared, but is set to null."
echo "username2 = ${username2:-`whoami`}"
#                            ^
# Will echo because of :- rather than just - in condition test.
# Compare to first instance, above.


#

# Once again:

variable=
# variable has been declared, but is set to null.

echo "${variable-0}"    # (no output)
echo "${variable:-1}"   # 1
#               ^

unset variable

echo "${variable-2}"    # 2
echo "${variable:-3}"   # 3

exit 0</PRE
></FONT
></TD
></TR
></TABLE
></P
><P
>The <I
CLASS="FIRSTTERM"
>default parameter</I
> construct
		  finds use in providing <SPAN
CLASS="QUOTE"
>"missing"</SPAN
> command-line
		  arguments in scripts.</P
><P
>		  <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>DEFAULT_FILENAME=generic.data
filename=${1:-$DEFAULT_FILENAME}
#  If not otherwise specified, the following command block operates
#+ on the file "generic.data".
#  Begin-Command-Block
#  ...
#  ...
#  ...
#  End-Command-Block



#  From "hanoi2.bash" example:
DISKS=${1:-E_NOPARAM}   # Must specify how many disks.
#  Set $DISKS to $1 command-line-parameter,
#+ or to $E_NOPARAM if that is unset.</PRE
></FONT
></TD
></TR
></TABLE
>
		</P
><P
>See also <A
HREF="special-chars.html#EX58"
>Example 3-4</A
>, <A
HREF="zeros.html#EX73"
>Example 31-2</A
>, and <A
HREF="contributed-scripts.html#COLLATZ"
>Example A-6</A
>.</P
><P
>Compare this method with <A
HREF="list-cons.html#ANDDEFAULT"
>using an <I
CLASS="FIRSTTERM"
>and
		  list</I
> to supply a default command-line
		  argument</A
>.</P
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${parameter=default}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${parameter:=default}</B
></TT
></DT
><DD
><P
><A
NAME="DEFPARAM"
></A
></P
><P
>If parameter not set, set it to
		  <I
CLASS="FIRSTTERM"
>default</I
>.</P
><P
>Both forms nearly equivalent. The <SPAN
CLASS="TOKEN"
>:</SPAN
>
		  makes a difference only when <TT
CLASS="VARNAME"
>$parameter</TT
>
		  has been declared and is null,
		    <A
NAME="AEN6310"
HREF="#FTN.AEN6310"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
>
		  as above.
		    </P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>echo ${var=abc}   # abc
echo ${var=xyz}   # abc
# $var had already been set to abc, so it did not change.</PRE
></FONT
></TD
></TR
></TABLE
></P
></DD
><DT
><A
NAME="PARAMALTV"
></A
><TT
CLASS="USERINPUT"
><B
>${parameter+alt_value}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${parameter:+alt_value}</B
></TT
></DT
><DD
><P
>If parameter set, use
		    <TT
CLASS="USERINPUT"
><B
>alt_value</B
></TT
>, else use null
		    string.</P
><P
>Both forms nearly equivalent. The <SPAN
CLASS="TOKEN"
>:</SPAN
>
		    makes a difference only when
		    <TT
CLASS="PARAMETER"
><I
>parameter</I
></TT
>
		    has been declared and is null, see below.</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>echo "###### \${parameter+alt_value} ########"
echo

a=${param1+xyz}
echo "a = $a"      # a =

param2=
a=${param2+xyz}
echo "a = $a"      # a = xyz

param3=123
a=${param3+xyz}
echo "a = $a"      # a = xyz

echo
echo "###### \${parameter:+alt_value} ########"
echo

a=${param4:+xyz}
echo "a = $a"      # a =

param5=
a=${param5:+xyz}
echo "a = $a"      # a =
# Different result from   a=${param5+xyz}

param6=123
a=${param6:+xyz}
echo "a = $a"      # a = xyz</PRE
></FONT
></TD
></TR
></TABLE
></P
></DD
><DT
><A
NAME="QERRMSG"
></A
><TT
CLASS="USERINPUT"
><B
>${parameter?err_msg}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${parameter:?err_msg}</B
></TT
></DT
><DD
><P
>If parameter set, use it, else print
                <I
CLASS="FIRSTTERM"
>err_msg</I
> and <EM
>abort
                the script</EM
> with an <A
HREF="exit-status.html#EXITSTATUSREF"
>exit status</A
> of
                <SPAN
CLASS="ERRORCODE"
>1</SPAN
>.</P
><P
>Both forms nearly equivalent. The <SPAN
CLASS="TOKEN"
>:</SPAN
>
		  makes a difference only when <TT
CLASS="PARAMETER"
><I
>parameter</I
></TT
>
		  has been declared and is null, as above.</P
></DD
></DL
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="EX6"
></A
><P
><B
>Example 10-7. Using parameter substitution and error messages</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash

#  Check some of the system's environmental variables.
#  This is good preventative maintenance.
#  If, for example, $USER, the name of the person at the console, is not set,
#+ the machine will not recognize you.

: ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?}
  echo
  echo "Name of the machine is $HOSTNAME."
  echo "You are $USER."
  echo "Your home directory is $HOME."
  echo "Your mail INBOX is located in $MAIL."
  echo
  echo "If you are reading this message,"
  echo "critical environmental variables have been set."
  echo
  echo

# ------------------------------------------------------

#  The ${variablename?} construction can also check
#+ for variables set within the script.

ThisVariable=Value-of-ThisVariable
#  Note, by the way, that string variables may be set
#+ to characters disallowed in their names.
: ${ThisVariable?}
echo "Value of ThisVariable is $ThisVariable".

echo; echo


: ${ZZXy23AB?"ZZXy23AB has not been set."}
#  Since ZZXy23AB has not been set,
#+ then the script terminates with an error message.

# You can specify the error message.
# : ${variablename?"ERROR MESSAGE"}


# Same result with:   dummy_variable=${ZZXy23AB?}
#                     dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."}
#
#                     echo ${ZZXy23AB?} &#62;/dev/null

#  Compare these methods of checking whether a variable has been set
#+ with "set -u" . . .



echo "You will not see this message, because script already terminated."

HERE=0
exit $HERE   # Will NOT exit here.

# In fact, this script will return an exit status (echo $?) of 1.</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="USAGEMESSAGE"
></A
><P
><B
>Example 10-8. Parameter substitution and <SPAN
CLASS="QUOTE"
>"usage"</SPAN
> messages</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

echo "These two lines echo only if command-line parameter given."
echo "command-line parameter = \"$1\""

exit 0  # Will exit here only if command-line parameter present.

# Check the exit status, both with and without command-line parameter.
# If command-line parameter present, then "$?" is 0.
# If not, then "$?" is 1.</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="FORMALPARA"
><P
><B
>Parameter substitution and/or expansion. </B
><A
NAME="PSUB2"
></A
>The following expressions are
		the complement to the <B
CLASS="COMMAND"
>match</B
>
		<TT
CLASS="REPLACEABLE"
><I
>in</I
></TT
> <B
CLASS="COMMAND"
>expr</B
>
		string operations (see <A
HREF="moreadv.html#EX45"
>Example 16-9</A
>).
		These particular ones are used mostly in parsing file
		path names.</P
></DIV
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
><A
NAME="PSOREX1"
></A
>Variable length / Substring removal</B
></P
><DL
><DT
><TT
CLASS="USERINPUT"
><B
>${#var}</B
></TT
></DT
><DD
><P
><TT
CLASS="USERINPUT"
><B
>String length</B
></TT
> (number
		    of characters in <TT
CLASS="VARNAME"
>$var</TT
>). For
		    an <A
HREF="arrays.html#ARRAYREF"
>array</A
>,
		    <B
CLASS="COMMAND"
>${#array}</B
> is the length of the
		    first element in the array.</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="90%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>		    Exceptions:

		  <P
></P
><UL
><LI
><P
><A
NAME="NUMPOSPARAM"
></A
></P
><P
>		      <B
CLASS="COMMAND"
>${#*}</B
> and
		      <B
CLASS="COMMAND"
>${#@}</B
> give the <EM
>number
		      of positional parameters</EM
>.
		    </P
></LI
><LI
><P
>		      For an array, <B
CLASS="COMMAND"
>${#array[*]}</B
> and
		      <B
CLASS="COMMAND"
>${#array[@]}</B
> give the number
		      of elements in the array.
		    </P
></LI
></UL
>
		  </P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="LENGTH"
></A
><P
><B
>Example 10-9. Length of a variable</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# length.sh

E_NO_ARGS=65

if [ $# -eq 0 ]  # Must have command-line args to demo script.
then
  echo "Please invoke this script with one or more command-line arguments."
  exit $E_NO_ARGS
fi  

var01=abcdEFGH28ij
echo "var01 = ${var01}"
echo "Length of var01 = ${#var01}"
# Now, let's try embedding a space.
var02="abcd EFGH28ij"
echo "var02 = ${var02}"
echo "Length of var02 = ${#var02}"

echo "Number of command-line arguments passed to script = ${#@}"
echo "Number of command-line arguments passed to script = ${#*}"

exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DD
><DT
><A
NAME="PSOREX2"
></A
><TT
CLASS="USERINPUT"
><B
>${var#Pattern}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${var##Pattern}</B
></TT
></DT
><DD
><P
><A
NAME="PSOREXSH"
></A
></P
><P
><B
CLASS="COMMAND"
>${var#Pattern} </B
>
		  Remove from <TT
CLASS="VARNAME"
>$var</TT
>
		  the <EM
>shortest</EM
> part of
		  <TT
CLASS="VARNAME"
>$Pattern</TT
> that matches
		  the <TT
CLASS="REPLACEABLE"
><I
>front end</I
></TT
> of
		  <TT
CLASS="VARNAME"
>$var</TT
>.
		</P
><P
><A
NAME="PSOREXLO"
></A
></P
><P
><B
CLASS="COMMAND"
>${var##Pattern} </B
>
		  Remove from <TT
CLASS="VARNAME"
>$var</TT
>
		  the <EM
>longest</EM
> part of
		  <TT
CLASS="VARNAME"
>$Pattern</TT
> that matches
		  the <TT
CLASS="REPLACEABLE"
><I
>front end</I
></TT
> of
		  <TT
CLASS="VARNAME"
>$var</TT
>.
		</P
><P
>A usage illustration from <A
HREF="contributed-scripts.html#DAYSBETWEEN"
>Example A-7</A
>:
		<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
># Function from "days-between.sh" example.
# Strips leading zero(s) from argument passed.

strip_leading_zero () #  Strip possible leading zero(s)
{                     #+ from argument passed.
  return=${1#0}       #  The "1" refers to "$1" -- passed arg.
}                     #  The "0" is what to remove from "$1" -- strips zeros.</PRE
></FONT
></TD
></TR
></TABLE
>
		</P
><P
>Manfred Schwarb's more elaborate variation of the
			above:</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>strip_leading_zero2 () # Strip possible leading zero(s), since otherwise
{                      # Bash will interpret such numbers as octal values.
  shopt -s extglob     # Turn on extended globbing.
  local val=${1##+(0)} # Use local variable, longest matching series of 0's.
  shopt -u extglob     # Turn off extended globbing.
  _strip_leading_zero2=${val:-0}
                       # If input was 0, return 0 instead of "".
}</PRE
></FONT
></TD
></TR
></TABLE
>
		</P
><P
>Another usage illustration:</P
><P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>echo `basename $PWD`        # Basename of current working directory.
echo "${PWD##*/}"           # Basename of current working directory.
echo
echo `basename $0`          # Name of script.
echo $0                     # Name of script.
echo "${0##*/}"             # Name of script.
echo
filename=test.data
echo "${filename##*.}"      # data
                            # Extension of filename.</PRE
></FONT
></TD
></TR
></TABLE
>
		</P
></DD
><DT
><A
NAME="PCTPATREF"
></A
><TT
CLASS="USERINPUT"
><B
>${var%Pattern}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${var%%Pattern}</B
></TT
></DT
><DD
><P
><A
NAME="PCTREP1"
></A
></P
><P
><B
CLASS="COMMAND"
>${var%Pattern}</B
>
		  Remove from <TT
CLASS="VARNAME"
>$var</TT
>
		  the <EM
>shortest</EM
> part of
		  <TT
CLASS="VARNAME"
>$Pattern</TT
> that matches
		  the <TT
CLASS="REPLACEABLE"
><I
>back end</I
></TT
> of
		  <TT
CLASS="VARNAME"
>$var</TT
>.  </P
><P
><A
NAME="PCTREP2"
></A
></P
><P
><B
CLASS="COMMAND"
>${var%%Pattern}</B
>
		  Remove from <TT
CLASS="VARNAME"
>$var</TT
>
		  the <EM
>longest</EM
> part of
		  <TT
CLASS="VARNAME"
>$Pattern</TT
> that matches
		  the <TT
CLASS="REPLACEABLE"
><I
>back end</I
></TT
> of
		  <TT
CLASS="VARNAME"
>$var</TT
>.  </P
></DD
></DL
></DIV
><P
><A
HREF="bashver2.html#BASH2REF"
>Version 2</A
> of Bash added
	      additional options.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="PATTMATCHING"
></A
><P
><B
>Example 10-10. Pattern matching in parameter substitution</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# patt-matching.sh

# Pattern matching  using the # ## % %% parameter substitution operators.

var1=abcd12345abc6789
pattern1=a*c  # * (wild card) matches everything between a - c.

echo
echo "var1 = $var1"           # abcd12345abc6789
echo "var1 = ${var1}"         # abcd12345abc6789
                              # (alternate form)
echo "Number of characters in ${var1} = ${#var1}"
echo

echo "pattern1 = $pattern1"   # a*c  (everything between 'a' and 'c')
echo "--------------"
echo '${var1#$pattern1}  =' "${var1#$pattern1}"    #         d12345abc6789
# Shortest possible match, strips out first 3 characters  abcd12345abc6789
#                                     ^^^^^               |-|
echo '${var1##$pattern1} =' "${var1##$pattern1}"   #                  6789      
# Longest possible match, strips out first 12 characters  abcd12345abc6789
#                                    ^^^^^                |----------|

echo; echo; echo

pattern2=b*9            # everything between 'b' and '9'
echo "var1 = $var1"     # Still  abcd12345abc6789
echo
echo "pattern2 = $pattern2"
echo "--------------"
echo '${var1%pattern2}  =' "${var1%$pattern2}"     #     abcd12345a
# Shortest possible match, strips out last 6 characters  abcd12345abc6789
#                                     ^^^^                         |----|
echo '${var1%%pattern2} =' "${var1%%$pattern2}"    #     a
# Longest possible match, strips out last 12 characters  abcd12345abc6789
#                                    ^^^^                 |-------------|

# Remember, # and ## work from the left end (beginning) of string,
#           % and %% work from the right end.

echo

exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="RFE"
></A
><P
><B
>Example 10-11. Renaming file extensions<SPAN
CLASS="TOKEN"
>:</SPAN
></B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# rfe.sh: Renaming file extensions.
#
#         rfe old_extension new_extension
#
# Example:
# To rename all *.gif files in working directory to *.jpg,
#          rfe gif jpg


E_BADARGS=65

case $# in
  0|1)             # The vertical bar means "or" in this context.
  echo "Usage: `basename $0` old_file_suffix new_file_suffix"
  exit $E_BADARGS  # If 0 or 1 arg, then bail out.
  ;;
esac


for filename in *.$1
# Traverse list of files ending with 1st argument.
do
  mv $filename ${filename%$1}$2
  #  Strip off part of filename matching 1st argument,
  #+ then append 2nd argument.
done

exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
><A
NAME="EXPREPL1"
></A
>Variable expansion / Substring
	      replacement</B
></P
><DL
><DT
></DT
><DD
><P
>These constructs have been adopted from
		  <I
CLASS="FIRSTTERM"
>ksh</I
>.</P
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${var:pos}</B
></TT
></DT
><DD
><P
>Variable <TT
CLASS="REPLACEABLE"
><I
>var</I
></TT
> expanded,
		    starting from offset <TT
CLASS="REPLACEABLE"
><I
>pos</I
></TT
>.
		  </P
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${var:pos:len}</B
></TT
></DT
><DD
><P
>Expansion to a max of <TT
CLASS="REPLACEABLE"
><I
>len</I
></TT
>
		    characters of variable <TT
CLASS="REPLACEABLE"
><I
>var</I
></TT
>, from offset
		    <TT
CLASS="REPLACEABLE"
><I
>pos</I
></TT
>. See <A
HREF="contributed-scripts.html#PW"
>Example A-13</A
>
		    for an example of the creative use of this operator.
		  </P
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${var/Pattern/Replacement}</B
></TT
></DT
><DD
><P
>First match of <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
>,
		    within <TT
CLASS="REPLACEABLE"
><I
>var</I
></TT
> replaced with
		    <TT
CLASS="REPLACEABLE"
><I
>Replacement</I
></TT
>.</P
><P
>If <TT
CLASS="REPLACEABLE"
><I
>Replacement</I
></TT
> is
		    omitted, then the first match of
		    <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
> is replaced by
		    <EM
>nothing</EM
>, that is, deleted.</P
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${var//Pattern/Replacement}</B
></TT
></DT
><DD
><DIV
CLASS="FORMALPARA"
><P
><B
>Global replacement. </B
><A
NAME="PSGLOB"
></A
>
		    All matches of <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
>,
		    within <TT
CLASS="REPLACEABLE"
><I
>var</I
></TT
> replaced with
		    <TT
CLASS="REPLACEABLE"
><I
>Replacement</I
></TT
>.</P
></DIV
><P
>As above, if <TT
CLASS="REPLACEABLE"
><I
>Replacement</I
></TT
>
		    is omitted, then all occurrences of
		    <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
> are replaced by
		    <EM
>nothing</EM
>, that is, deleted.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="EX7"
></A
><P
><B
>Example 10-12. Using pattern matching to parse arbitrary strings</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash

var1=abcd-1234-defg
echo "var1 = $var1"

t=${var1#*-*}
echo "var1 (with everything, up to and including first - stripped out) = $t"
#  t=${var1#*-}  works just the same,
#+ since # matches the shortest string,
#+ and * matches everything preceding, including an empty string.
# (Thanks, Stephane Chazelas, for pointing this out.)

t=${var1##*-*}
echo "If var1 contains a \"-\", returns empty string...   var1 = $t"


t=${var1%*-*}
echo "var1 (with everything from the last - on stripped out) = $t"

echo

# -------------------------------------------
path_name=/home/bozo/ideas/thoughts.for.today
# -------------------------------------------
echo "path_name = $path_name"
t=${path_name##/*/}
echo "path_name, stripped of prefixes = $t"
# Same effect as   t=`basename $path_name` in this particular case.
#  t=${path_name%/}; t=${t##*/}   is a more general solution,
#+ but still fails sometimes.
#  If $path_name ends with a newline, then `basename $path_name` will not work,
#+ but the above expression will.
# (Thanks, S.C.)

t=${path_name%/*.*}
# Same effect as   t=`dirname $path_name`
echo "path_name, stripped of suffixes = $t"
# These will fail in some cases, such as "../", "/foo////", # "foo/", "/".
#  Removing suffixes, especially when the basename has no suffix,
#+ but the dirname does, also complicates matters.
# (Thanks, S.C.)

echo

t=${path_name:11}
echo "$path_name, with first 11 chars stripped off = $t"
t=${path_name:11:5}
echo "$path_name, with first 11 chars stripped off, length 5 = $t"

echo

t=${path_name/bozo/clown}
echo "$path_name with \"bozo\" replaced  by \"clown\" = $t"
t=${path_name/today/}
echo "$path_name with \"today\" deleted = $t"
t=${path_name//o/O}
echo "$path_name with all o's capitalized = $t"
t=${path_name//o/}
echo "$path_name with all o's deleted = $t"

exit 0</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${var/#Pattern/Replacement}</B
></TT
></DT
><DD
><P
>If <I
CLASS="FIRSTTERM"
>prefix</I
> of
		  <TT
CLASS="REPLACEABLE"
><I
>var</I
></TT
> matches
		  <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
>, then substitute
		  <TT
CLASS="REPLACEABLE"
><I
>Replacement</I
></TT
> for
		  <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
>.</P
></DD
><DT
><TT
CLASS="USERINPUT"
><B
>${var/%Pattern/Replacement}</B
></TT
></DT
><DD
><P
>If <I
CLASS="FIRSTTERM"
>suffix</I
> of
		  <TT
CLASS="REPLACEABLE"
><I
>var</I
></TT
> matches
		  <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
>, then substitute
		  <TT
CLASS="REPLACEABLE"
><I
>Replacement</I
></TT
> for
		  <TT
CLASS="REPLACEABLE"
><I
>Pattern</I
></TT
>.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="VARMATCH"
></A
><P
><B
>Example 10-13. Matching patterns at prefix or suffix of string</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
>#!/bin/bash
# var-match.sh:
# Demo of pattern replacement at prefix / suffix of string.

v0=abc1234zip1234abc    # Original variable.
echo "v0 = $v0"         # abc1234zip1234abc
echo

# Match at prefix (beginning) of string.
v1=${v0/#abc/ABCDEF}    # abc1234zip1234abc
                        # |-|
echo "v1 = $v1"         # ABCDEF1234zip1234abc
                        # |----|

# Match at suffix (end) of string.
v2=${v0/%abc/ABCDEF}    # abc1234zip123abc
                        #              |-|
echo "v2 = $v2"         # abc1234zip1234ABCDEF
                        #               |----|

echo

#  ----------------------------------------------------
#  Must match at beginning / end of string,
#+ otherwise no replacement results.
#  ----------------------------------------------------
v3=${v0/#123/000}       # Matches, but not at beginning.
echo "v3 = $v3"         # abc1234zip1234abc
                        # NO REPLACEMENT.
v4=${v0/%123/000}       # Matches, but not at end.
echo "v4 = $v4"         # abc1234zip1234abc
                        # NO REPLACEMENT.

exit 0			</PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DD
><DT
><A
NAME="VARPREFIXM"
></A
><TT
CLASS="USERINPUT"
><B
>${!varprefix*}</B
></TT
>, <TT
CLASS="USERINPUT"
><B
>${!varprefix@}</B
></TT
></DT
><DD
><P
>Matches <EM
>names</EM
> of all
		  previously declared variables beginning
		    with <TT
CLASS="PARAMETER"
><I
>varprefix</I
></TT
>.
		      <TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
># This is a variation on indirect reference, but with a * or @.
# Bash, version 2.04, adds this feature.

xyz23=whatever
xyz24=

a=${!xyz*}         #  Expands to *names* of declared variables
# ^ ^   ^           + beginning with "xyz".
echo "a = $a"      #  a = xyz23 xyz24
a=${!xyz@}         #  Same as above.
echo "a = $a"      #  a = xyz23 xyz24

echo "---"

abc23=something_else
b=${!abc*}
echo "b = $b"      #  b = abc23
c=${!b}            #  Now, the more familiar type of indirect reference.
echo $c            #  something_else</PRE
></FONT
></TD
></TR
></TABLE
>
                  </P
></DD
></DL
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN6310"
HREF="parameter-substitution.html#AEN6310"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>If $parameter is null in a
		      non-interactive script, it will terminate with a <A
HREF="exitcodes.html#EXITCODESREF"
><SPAN
CLASS="RETURNVALUE"
>127</SPAN
>
		      exit status</A
> (the Bash error code for
		      <SPAN
CLASS="QUOTE"
>"command not found"</SPAN
>).</P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="string-manipulation.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="loops.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Manipulating Strings</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="manipulatingvars.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Loops and Branches</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>